import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';

///可设置动画的列表。
///内部使用的是[SingleChildScrollView]实现，
///需要外层设置定义可约束高度。
class KqAnimateListView<T> extends StatefulWidget {
  ///数据
  final List<T> data;

  ///列表
  final Widget Function(T t) item;

  ///动画自定义
  final IAnimate? animate;

  ///是否需要执行动画
  final bool isNeedAnimate;

  ///是否需要每次刷新时都执行动画
  final bool isNeedFlashEveryTime;

  const KqAnimateListView({
    super.key,
    required this.item,
    required this.data,
    this.animate,
    this.isNeedFlashEveryTime = false,
    this.isNeedAnimate = true,
  });

  @override
  State<StatefulWidget> createState() => _KqAnimateListViewState<T>();
}

class _KqAnimateListViewState<T> extends State<KqAnimateListView<T>>
    with TickerProviderStateMixin {
  late IAnimate animate;
  late AnimationController controller;
  late CurvedAnimation curvedAnimation;
  late Animation animation;
  bool isInitState = true;

  @override
  void initState() {
    super.initState();
    isInitState = true;
    animate = widget.animate ?? ScaleAnimate();
    animate.init(widget.data.length);
    controller = animate.getAnimationController(this);
    curvedAnimation = CurvedAnimation(parent: controller, curve: Curves.ease);
    animation = animate.getAnimation(curvedAnimation, this);
    if (widget.isNeedAnimate) {
      //启动动画(正向执行)
      controller.forward();
    }
  }

  @override
  void didUpdateWidget(covariant KqAnimateListView<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    isInitState = false;
    if (widget.isNeedAnimate && widget.isNeedFlashEveryTime) {
      animate = widget.animate ?? ScaleAnimate();
      animate.init(widget.data.length);
      controller.dispose();
      controller = animate.getAnimationController(this);
      curvedAnimation = CurvedAnimation(parent: controller, curve: Curves.ease);
      animation = animate.getAnimation(curvedAnimation, this);
      //启动动画(正向执行)
      controller.forward();
    }
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox.expand(
      child: SingleChildScrollView(
        child: Column(
          children: _getChildren(context),
        ),
      ),
    );
  }

  List<Widget> _getChildren(BuildContext context) {
    List<Widget> list = [];
    for (int i = 0; i < widget.data.length; i++) {
      Widget child = widget.item.call(widget.data[i]);
      list.add(
        isInitState && widget.isNeedAnimate || widget.isNeedFlashEveryTime
            ? animate.animate(context, i, child, animation, controller)
            : child,
      );
    }
    return list;
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

///动画抽象类。
///实现该类，定制自己的列表动画。
abstract class IAnimate {
  ///初始化
  ///[length] 列表长度
  void init(int length);

  ///获取AnimationController
  AnimationController getAnimationController(TickerProvider provider);

  ///获取Animation
  Animation getAnimation(
      Animation<double> animation, State<StatefulWidget> state);

  ///定制自己的动画，每一个item都会调用到animate，
  ///当需要差异动画时需要根据[index]计算不同item的动画时机
  ///[widget] 执行动画之后的widget
  ///[index] 列表的item的index
  Widget animate(
    BuildContext context,
    int index,
    Widget widget,
    Animation animation,
    AnimationController controller,
  );
}

///水平移动动画
class HorizontalAnimate extends IAnimate {
  ///动画执行时长比例
  static double rate = 0.9;

  ///单个动画执行长度
  static double baseGap = 1000.0;

  ///两个个动画执行间隔长度
  static double twoGap = 80.0;

  ///动画执行的总长度，根据列表长度动态计算值
  late double gap;

  ///动画是从左边还是右边开始执行
  HorizontalAnimateDirection direction;

  HorizontalAnimate({this.direction = HorizontalAnimateDirection.right});

  @override
  void init(int length) {
    gap = length * twoGap + baseGap;
  }

  @override
  Widget animate(BuildContext context, int index, Widget widget,
      Animation animation, AnimationController controller) {
    double width = context.width;

    ///范围0->1
    double mix = (animation.value - twoGap * index) / baseGap;
    if (mix > 1) {
      mix = 1;
    }
    double left = width * (1 - mix);
    return Container(
      transform: Matrix4.translationValues(
          direction == HorizontalAnimateDirection.left ? -left : left, 0, 0),
      child: widget,
    );
  }

  @override
  AnimationController getAnimationController(TickerProvider provider) {
    return AnimationController(
        duration: Duration(milliseconds: (gap * rate).toInt()),
        vsync: provider);
  }

  @override
  Animation getAnimation(
      Animation<double> animation, State<StatefulWidget> state) {
    return Tween(begin: 0.0, end: gap).animate(animation)
      ..addListener(() {
        if (state.mounted) {
          state.setState(() {});
        }
      });
  }
}

enum HorizontalAnimateDirection {
  ///左边
  left,

  ///右边
  right;
}

///缩放动画
class ScaleAnimate extends IAnimate {
  ///动画执行时长比例
  static double rate = 0.4;

  ///单个动画执行长度
  static double baseGap = 1000.0;

  ///两个个动画执行间隔长度
  static double twoGap = 200.0;

  ///动画执行的总长度，根据列表长度动态计算值
  late double gap;

  @override
  Widget animate(BuildContext context, int index, Widget widget,
      Animation animation, AnimationController controller) {
    double width = context.width;

    ///范围0.5->1
    double mix = ((animation.value - twoGap * index) / baseGap + 1) / 2;
    if (mix > 1) {
      mix = 1;
    }
    double widthMix = width * mix;
    return SizedBox(
      width: max(0, widthMix),
      child: widget,
    );
  }

  @override
  AnimationController getAnimationController(TickerProvider provider) {
    return AnimationController(
        duration: Duration(milliseconds: (gap * rate).toInt()),
        vsync: provider);
  }

  @override
  Animation getAnimation(
      Animation<double> animation, State<StatefulWidget> state) {
    return Tween(begin: 0.0, end: gap).animate(animation)
      ..addListener(() {
        if (state.mounted) {
          state.setState(() {});
        }
      });
  }

  @override
  void init(int length) {
    gap = length * twoGap + baseGap;
  }
}
